#include "Weather.h"
#include "../Managers/GameManager.h"
#include <libtcod\libtcod.hpp>

Sun::Sun(const Vec2i &rise_pos, const Vec2i &set_pos, int radius, int day_cycle)
	: rise_pos(rise_pos), set_pos(set_pos), radius(radius), day_cycle(day_cycle)
{
	ambient_dawn = TCODColor(196,25,25);
	ambient_noon = TCODColor(220,200,64);
	ambient_day  = TCODColor(255,255,195);
	ambient_dusk = TCODColor(60,60,196);
	ambient_night = TCODColor(20,20,128);

	color = TCODColor(255,253,195);
	coef = 0.0f;
	sun_climbing = true;
}

Sun::~Sun()
{
}

void Sun::update(float dt)
{
	static float local_dt=7.0f*3600.0f;
	static float local_dt2 = local_dt;
	local_dt += dt;
	local_dt2 += dt;
	if(local_dt > day_cycle)
		local_dt = 0.0f;

	//Half a day (12 hours)
	if(local_dt2 > (day_cycle/2.0f))
		local_dt2 = 0.0f;

	hour = local_dt / 3600.0f;
	updateAmbient();

	//simple linear interpolation
	static float PI = 3.141592653589793f;
	float mu = local_dt / (day_cycle);
	float mu2 = (1.0f-cosf(mu*PI))/2.0f;

	float mu3 = local_dt2 / (day_cycle/2.0f);
	static float last_m4 = 0.0f;
	float mu4 = (1.0f-cosf(mu3*PI))/2.0f;
	if(mu4 - last_m4 < 0.0f)
		sun_climbing = !sun_climbing;
	last_m4 = mu4;

	float x = rise_pos.x()*(1.0f-mu2)+set_pos.x()*mu2;
	float y = 0.0f;
	if(sun_climbing)
		y = radius*mu4;
	else
		y = radius - radius*mu4;
	float z = rise_pos.y()*(1.0f-mu2)+set_pos.y()*mu2;
		
	pos.x() = (int)x;
	pos.y() = (int)z;

	pos3f.x() = x;
	pos3f.y() = y;
	pos3f.z() = z;
}

void Sun::updateAmbient()
{
	if(hour > 21.0f || hour < 6.0f)
	{
		ambient = ambient_night;
		coef = 0.0f;
	}
	else if(hour < 7.0f)
	{
		coef = (hour - 6.0f);
		ambient = TCODColor::lerp(ambient_night,ambient_dawn,coef);
		coef /= 3.0f;
	}
	else if(hour < 8.0f)
	{
		coef = (hour - 7.0f);
		ambient = TCODColor::lerp(ambient_dawn,ambient_noon,coef);
		coef = 0.33333 + coef/3.0f;
	}
	else if(hour < 9.0f)
	{
		coef = (hour - 8.0f);
		ambient = TCODColor::lerp(ambient_noon,ambient_day,coef);
		coef = 0.66666 + coef/3.0f;
	}
	else if(hour < 18.0f)
	{
		ambient = ambient_day;
		coef = 1.0f;
	}
	else if(hour < 19.0f)
	{
		coef = (hour - 18.0f);
		ambient = TCODColor::lerp(ambient_day,ambient_noon,coef);
		coef = 0.66666 + (1.0f-coef)/3.0f;
	}
	else if(hour < 20.0f)
	{
		coef = (hour - 19.0f);
		ambient = TCODColor::lerp(ambient_noon,ambient_dawn,coef);
		coef = 0.33333 + (1.0f-coef)/3.0f;
	}
	else if(hour < 21.0f)
	{
		coef = (hour - 20.0f);
		ambient = TCODColor::lerp(ambient_dawn,ambient_night,coef);
		coef = (1.0f-coef)/3.0f;
	}
}

std::string Sun::getHourDescription() const
{
	if(hour > 21.0f || hour < 6.0f)
	{
		return "It's night.";
	}
	else if(hour < 7.0f)
	{
		return "It's early morning.";
	}
	else if(hour < 8.0f)
	{
		return "It's morning.";
	}
	else if(hour < 9.0f)
	{
		return "It's noon.";
	}
	else if(hour < 18.0f)
	{
		return "It's day.";
	}
	else if(hour < 19.0f)
	{
		return "It's early evening.";
	}
	else if(hour < 20.0f)
	{
		return "It's evening.";
	}
	else if(hour < 21.0f)
	{
		return "It's dusk.";
	}
	return "";
}

Weather::Weather()
{
	sun = std::make_shared<Sun>(Vec2i(400, 0), Vec2i(0, 400));
}

Weather::~Weather()
{
}

void Weather::update(float dt)
{
	sun->update(dt*60*12);
	GameManager::getSingleton()->getStoryConsole()->print(0, 1, sun->getHourDescription().c_str());
}
